class {{{classname}}} {
{{>dart_constructor}}
{{#vars}}
  {{#description}}
  /// {{{.}}}
  {{/description}}
  {{^isEnum}}
    {{#minimum}}
      {{#description}}
  ///
      {{/description}}
  /// Minimum value: {{{.}}}
    {{/minimum}}
    {{#maximum}}
      {{#description}}
        {{^minimum}}
  ///
        {{/minimum}}
      {{/description}}
  /// Maximum value: {{{.}}}
    {{/maximum}}
    {{^isNullable}}
      {{^required}}
        {{^defaultValue}}
  ///
  /// Please note: This property should have been non-nullable! Since the specification file
  /// does not include a default value (using the "default:" property), however, the generated
  /// source code must fall back to having a nullable type.
  /// Consider adding a "default:" property in the specification file to hide this note.
  ///
        {{/defaultValue}}
      {{/required}}
    {{/isNullable}}
  {{/isEnum}}
  {{#isArray}}{{#uniqueItems}}Set{{/uniqueItems}}{{^uniqueItems}}List{{/uniqueItems}}<{{{items.dataType}}}{{#items.isNullable}}?{{/items.isNullable}}>{{/isArray}}{{^isArray}}{{{datatypeWithEnum}}}{{/isArray}}{{#isNullable}}?{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}?{{/defaultValue}}{{/required}}{{/isNullable}} {{{name}}};

{{/vars}}
  @override
  bool operator ==(Object other) => identical(this, other) || other is {{{classname}}} &&
  {{#vars}}
    {{#isMap}}_deepEquality.equals(other.{{{name}}}, {{{name}}}){{/isMap}}{{^isMap}}{{#isArray}}_deepEquality.equals(other.{{{name}}}, {{{name}}}){{/isArray}}{{^isArray}}other.{{{name}}} == {{{name}}}{{/isArray}}{{/isMap}}{{^-last}} &&{{/-last}}{{#-last}};{{/-last}}
  {{/vars}}

  @override
  int get hashCode =>
    // ignore: unnecessary_parenthesis
  {{#vars}}
    ({{#isNullable}}{{{name}}} == null ? 0 : {{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}{{{name}}} == null ? 0 : {{/defaultValue}}{{/required}}{{/isNullable}}{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.hashCode){{^-last}} +{{/-last}}{{#-last}};{{/-last}}
  {{/vars}}

  @override
  String toString() => '{{{classname}}}[{{#vars}}{{{name}}}=${{{name}}}{{^-last}}, {{/-last}}{{/vars}}]';

  Map<String, dynamic> toJson() {
    final json = <String, dynamic>{};
  {{#vars}}
    {{#isNullable}}
    if (this.{{{name}}} != null) {
    {{/isNullable}}
    {{^isNullable}}
      {{^required}}
        {{^defaultValue}}
    if (this.{{{name}}} != null) {
        {{/defaultValue}}
      {{/required}}
    {{/isNullable}}
    {{#isDateTime}}
      {{#pattern}}
      json[r'{{{baseName}}}'] = _isEpochMarker(r'{{{pattern}}}')
        ? this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.millisecondsSinceEpoch
        : this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.toUtc().toIso8601String();
      {{/pattern}}
      {{^pattern}}
      json[r'{{{baseName}}}'] = this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.toUtc().toIso8601String();
      {{/pattern}}
    {{/isDateTime}}
    {{#isDate}}
      {{#pattern}}
      json[r'{{{baseName}}}'] = _isEpochMarker(r'{{{pattern}}}')
        ? this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.millisecondsSinceEpoch
        : _dateFormatter.format(this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.toUtc());
      {{/pattern}}
      {{^pattern}}
      json[r'{{{baseName}}}'] = _dateFormatter.format(this.{{{name}}}{{#isNullable}}!{{/isNullable}}{{^isNullable}}{{^required}}{{^defaultValue}}!{{/defaultValue}}{{/required}}{{/isNullable}}.toUtc());
      {{/pattern}}
    {{/isDate}}
    {{^isDateTime}}
      {{^isDate}}
      json[r'{{{baseName}}}'] = this.{{{name}}}{{#isArray}}{{#uniqueItems}}{{#isNullable}}!{{/isNullable}}.toList(growable: false){{/uniqueItems}}{{/isArray}};
      {{/isDate}}
    {{/isDateTime}}
    {{#isNullable}}
    } else {
    //  json[r'{{{baseName}}}'] = null;
    }
    {{/isNullable}}
    {{^isNullable}}
      {{^required}}
        {{^defaultValue}}
    } else {
    //  json[r'{{{baseName}}}'] = null;
    }
        {{/defaultValue}}
      {{/required}}
    {{/isNullable}}
  {{/vars}}
    return json;
  }

  /// Returns a new [{{{classname}}}] instance and imports its values from
  /// [value] if it's a [Map], null otherwise.
  // ignore: prefer_constructors_over_static_methods
  static {{{classname}}}? fromJson(dynamic value) {
    upgradeDto(value, "{{{classname}}}");
    if (value is Map) {
      final json = value.cast<String, dynamic>();

      return {{{classname}}}(
  {{#vars}}
    {{#isDateTime}}
        {{{name}}}: mapDateTime(json, r'{{{baseName}}}', r'{{{pattern}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
    {{/isDateTime}}
    {{#isDate}}
        {{{name}}}: mapDateTime(json, r'{{{baseName}}}', r'{{{pattern}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
    {{/isDate}}
    {{^isDateTime}}
      {{^isDate}}
        {{#complexType}}
          {{#isArray}}
            {{#items.isArray}}
        {{{name}}}: json[r'{{{baseName}}}'] is List
          ? (json[r'{{{baseName}}}'] as List).map((e) =>
              {{#items.complexType}}
              {{items.complexType}}.listFromJson(json[r'{{{baseName}}}']){{#uniqueItems}}.toSet(){{/uniqueItems}}
              {{/items.complexType}}
              {{^items.complexType}}
              e == null ? {{#items.isNullable}}null{{/items.isNullable}}{{^items.isNullable}}const  <{{items.items.dataType}}>[]{{/items.isNullable}} : (e as List).cast<{{items.items.dataType}}>()
              {{/items.complexType}}
            ).toList()
          :  {{#isNullable}}null{{/isNullable}}{{^isNullable}}const []{{/isNullable}},
            {{/items.isArray}}
            {{^items.isArray}}
        {{{name}}}: {{{complexType}}}.listFromJson(json[r'{{{baseName}}}']){{#uniqueItems}}.toSet(){{/uniqueItems}},
            {{/items.isArray}}
          {{/isArray}}
          {{^isArray}}
            {{#isMap}}
              {{#items.isArray}}
        {{{name}}}: json[r'{{{baseName}}}'] == null
          ? {{#defaultValue}}{{{.}}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}}
                {{#items.complexType}}
            : {{items.complexType}}.mapListFromJson(json[r'{{{baseName}}}']),
                {{/items.complexType}}
                {{^items.complexType}}
            : mapCastOfType<String, List>(json, r'{{{baseName}}}'),
                {{/items.complexType}}
              {{/items.isArray}}
              {{^items.isArray}}
                {{#items.isMap}}
                  {{#items.complexType}}
        {{{name}}}: {{items.complexType}}.mapFromJson(json[r'{{{baseName}}}']),
                  {{/items.complexType}}
                  {{^items.complexType}}
        {{{name}}}: mapCastOfType<String, dynamic>(json, r'{{{baseName}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
                  {{/items.complexType}}
                {{/items.isMap}}
                {{^items.isMap}}
                  {{#items.complexType}}
        {{{name}}}: {{{items.complexType}}}.mapFromJson(json[r'{{{baseName}}}']),
                  {{/items.complexType}}
                  {{^items.complexType}}
        {{{name}}}: mapCastOfType<String, {{items.dataType}}>(json, r'{{{baseName}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
                  {{/items.complexType}}
                {{/items.isMap}}
              {{/items.isArray}}
            {{/isMap}}
            {{^isMap}}
              {{#isBinary}}
        {{{name}}}: null, // No support for decoding binary content from JSON
              {{/isBinary}}
              {{^isBinary}}
        {{{name}}}: {{{complexType}}}.fromJson(json[r'{{{baseName}}}']){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
              {{/isBinary}}
            {{/isMap}}
          {{/isArray}}
        {{/complexType}}
        {{^complexType}}
          {{#isArray}}
            {{#isEnum}}
        {{{name}}}: {{{items.datatypeWithEnum}}}.listFromJson(json[r'{{{baseName}}}']){{#uniqueItems}}.toSet(){{/uniqueItems}},
            {{/isEnum}}
            {{^isEnum}}
        {{{name}}}: json[r'{{{baseName}}}'] is Iterable
            ? (json[r'{{{baseName}}}'] as Iterable).cast<{{{items.datatype}}}>().{{#uniqueItems}}toSet(){{/uniqueItems}}{{^uniqueItems}}toList(growable: false){{/uniqueItems}}
            : {{#defaultValue}}{{{.}}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}},
            {{/isEnum}}
          {{/isArray}}
          {{^isArray}}
            {{#isMap}}
        {{{name}}}: mapCastOfType<String, {{{items.datatype}}}>(json, r'{{{baseName}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
            {{/isMap}}
            {{^isMap}}
              {{#isNumber}}
        {{{name}}}: {{#isNullable}}json[r'{{{baseName}}}'] == null
            ? {{#defaultValue}}{{{.}}}{{/defaultValue}}{{^defaultValue}}null{{/defaultValue}}
            : {{/isNullable}}{{{datatypeWithEnum}}}.parse('${json[r'{{{baseName}}}']}'),
              {{/isNumber}}
              {{#isDouble}}
        {{{name}}}: (mapValueOfType<num>(json, r'{{{baseName}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}}){{#isNullable}}?{{/isNullable}}.toDouble(),
              {{/isDouble}}
              {{^isDouble}}
              {{^isNumber}}
                {{^isEnum}}
        {{{name}}}: mapValueOfType<{{{datatypeWithEnum}}}>(json, r'{{{baseName}}}'){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
                {{/isEnum}}
                {{#isEnum}}
        {{{name}}}: {{{enumName}}}.fromJson(json[r'{{{baseName}}}']){{#required}}{{^isNullable}}!{{/isNullable}}{{/required}}{{^required}}{{#defaultValue}} ?? {{{.}}}{{/defaultValue}}{{/required}},
                {{/isEnum}}
              {{/isNumber}}
              {{/isDouble}}
            {{/isMap}}
          {{/isArray}}
        {{/complexType}}
      {{/isDate}}
    {{/isDateTime}}
  {{/vars}}
      );
    }
    return null;
  }

  static List<{{{classname}}}> listFromJson(dynamic json, {bool growable = false,}) {
    final result = <{{{classname}}}>[];
    if (json is List && json.isNotEmpty) {
      for (final row in json) {
        final value = {{{classname}}}.fromJson(row);
        if (value != null) {
          result.add(value);
        }
      }
    }
    return result.toList(growable: growable);
  }

  static Map<String, {{{classname}}}> mapFromJson(dynamic json) {
    final map = <String, {{{classname}}}>{};
    if (json is Map && json.isNotEmpty) {
      json = json.cast<String, dynamic>(); // ignore: parameter_assignments
      for (final entry in json.entries) {
        final value = {{{classname}}}.fromJson(entry.value);
        if (value != null) {
          map[entry.key] = value;
        }
      }
    }
    return map;
  }

  // maps a json object with a list of {{{classname}}}-objects as value to a dart map
  static Map<String, List<{{{classname}}}>> mapListFromJson(dynamic json, {bool growable = false,}) {
    final map = <String, List<{{{classname}}}>>{};
    if (json is Map && json.isNotEmpty) {
      // ignore: parameter_assignments
      json = json.cast<String, dynamic>();
      for (final entry in json.entries) {
        map[entry.key] = {{{classname}}}.listFromJson(entry.value, growable: growable,);
      }
    }
    return map;
  }

  /// The list of required keys that must be present in a JSON.
  static const requiredKeys = <String>{
{{#vars}}
  {{#required}}
    '{{{baseName}}}',
  {{/required}}
{{/vars}}
  };
}
{{#vars}}
    {{^isModel}}
    {{#isEnum}}
        {{^isContainer}}

{{>serialization/native/native_enum_inline}}
        {{/isContainer}}
        {{#isContainer}}
            {{#mostInnerItems}}

{{>serialization/native/native_enum_inline}}
            {{/mostInnerItems}}
        {{/isContainer}}
    {{/isEnum}}
    {{/isModel}}
{{/vars}}
